/**
 * Copyright 2012-2013 University Of Southern California
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.workflowsim.scheduling;

import java.util.Iterator;
import org.cloudbus.cloudsim.Cloudlet;
import org.workflowsim.CondorVM;
import org.workflowsim.WorkflowSimTags;

/**
 * The FCFS algorithm. 
 * FCFS 算法
 * 算法说明：
 * FCFS(First Come First Served )先来先服务，
 * 在计算机领域中，有时被用以描述数据结构中的队列性质。
 * 先到的任务先处理，后到的任务后处理
 * 在本例中，首先通过迭代器从云任务列表里取出第一个云任务，然后再通过一个迭代器
 * 从虚拟机列表里取出一个虚拟机，如果这个虚拟机的状态是空闲的，那么就将这个云任务
 * 绑定给虚拟机（通过绑定ID的方式），绑定完就把这个虚拟机的状态调为忙碌状态，防止再次绑定
 * 任务给这个虚拟机。最后将云任务添加进调度列表
 * @author Weiwei Chen
 * @since WorkflowSim Toolkit 1.0
 * @date Apr 9, 2013
 */
public class FCFSSchedulingAlgorithm extends BaseSchedulingAlgorithm {

    /**
     * The main function
     * 主函数
     */
    @Override
    public void run() {

    	/*
    	 * 在for循环中添加一个Java迭代器，用于遍历整个云任务列表
    	 */
        for (Iterator it = getCloudletList().iterator(); it.hasNext();) {
        	//.next()方法会返回一个Object类型的值，因此需要转型成Cloudlet才能赋值给Cloudlet类型的对象cloudlet
            Cloudlet cloudlet = (Cloudlet) it.next();
            boolean stillHasVm = false;
            /*
             * 在for循环中添加一个Java迭代器，用于遍历整个虚拟机列表
             */
            for (Iterator itc = getVmList().iterator(); itc.hasNext();) {
            	//.next()方法会返回一个Object类型的值，因此需要转型成CondorVM才能赋值给CondorVM类型的对象vm
                CondorVM vm = (CondorVM) itc.next();
                //如果当前虚拟机的状态是空闲的
                if (vm.getState() == WorkflowSimTags.VM_STATUS_IDLE) {
                    stillHasVm = true;
                    //那么就把虚拟机的状态改为忙碌
                    vm.setState(WorkflowSimTags.VM_STATUS_BUSY);
                    //并且把云任务的ID和当前虚拟机的ID绑定在一起
                    cloudlet.setVmId(vm.getId());
                    //并且将云任务添加进调度列表
                    getScheduledList().add(cloudlet);
                    break;
                }
            }//第二个for结束
            //no vm available 
            //当没有虚拟机可以分配时，跳出分配循环
            if (!stillHasVm) {
                break;
            }
        }//第一个for结束
    }
}
